﻿using System;
using System.Security.Cryptography;

namespace RENACOM_ORM.Helpers
{
    /// <summary>
    /// 
    /// </summary>
    public static class RandomGenerator
    {
        private static readonly RNGCryptoServiceProvider RNGCrypto = new RNGCryptoServiceProvider();

        /// <summary>
        /// Gets the next int32.
        /// </summary>
        /// <returns></returns>
        public static int GetNextInt32()
        { return GetNextInt32(0, int.MaxValue); }

        /// <summary>
        /// Gets the next int32.
        /// </summary>
        /// <param name="__Low">The low.</param>
        /// <param name="__Hi">The hi.</param>
        /// <returns></returns>
        public static int GetNextInt32(int __Low, int __Hi)
        { return (int)GetNextInt64(__Low, __Hi); }

        /// <summary>
        /// Gets the next int64.
        /// </summary>
        /// <returns></returns>
        public static long GetNextInt64()
        { return GetNextInt64(0, long.MaxValue); }

        /// <summary>
        /// Gets the next int64.
        /// </summary>
        /// <param name="__Low">The low.</param>
        /// <param name="__Hi">The hi.</param>
        /// <returns></returns>
        public static long GetNextInt64(long __Low, long __Hi)
        {
            if (__Low >= __Hi) throw new ArgumentException("low must be < hi");

            //Generate a random double
            byte[] _Buffer = new byte[8];
            RNGCrypto.GetBytes(_Buffer);
            long _LongRand = BitConverter.ToInt64(_Buffer, 0);

            return (Math.Abs(_LongRand % (__Hi - __Low)) + __Low);            
        }

        /// <summary>
        /// Gets the next double.
        /// </summary>
        /// <returns></returns>
        public static double GetNextDouble()
        { return GetNextDouble(0, double.MaxValue); }

        /// <summary>
        /// Gets the next double.
        /// </summary>
        /// <param name="__Low">The low.</param>
        /// <param name="__Hi">The hi.</param>
        /// <returns></returns>
        public static double GetNextDouble(double __Low, double __Hi)
        {
            if (__Low >= __Hi) throw new ArgumentException("low must be < hi");
            
            //Generate a random double
            byte[] _Buffer = new byte[8];
            RNGCrypto.GetBytes(_Buffer);
            double _LongRand = BitConverter.ToDouble(_Buffer, 0);

            return (Math.Abs(_LongRand % (__Hi - __Low)) + __Low); 
        }
    }
}
